#pragma once
using namespace System;
using namespace System::Runtime::InteropServices;
using namespace SimulatorBase;

#pragma unmanaged
#include "SimulatorControl.h"

#include "RobotAppDef.h"

#pragma managed
namespace RobotEmulator {

ref class RobotApp :
public SimulatorBase::RobotBase
{
public:
	RobotApp(void){
		this->simCon = new ::SimulatorControl();
		this->robot = new ::PCStartup();
	}
	~RobotApp(void){
	}
	!RobotApp(void){
			ssmGC.Free();
			slbGC.Free();
			slsGC.Free();
			smGC.Free();
			cmGC.Free();
			omGC.Free();
			cclGC.Free();
			ccwGC.Free();
			ccsGC.Free();
			clGC.Free();
			pGC.Free();
			ssdGC.Free();
			ssiGC.Free();
			ssGC.Free();
			bsGC.Free();

		}


		virtual void SetDelegatorSetSensorMode(RobotBase::SetSensorModeHandler^ handler){
			ssmGC = GCHandle::Alloc(handler);
			IntPtr ptr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::SetSensorModeFp fp = static_cast<::SimulatorControl::SetSensorModeFp>(ptr.ToPointer());
			simCon->SetDelegatorSetSensorModeFp(fp);
		}
		virtual void SetDelegatorSetLightBrightness(RobotBase::SetLightBrightnessHandler^ handler)
		{
			slbGC = GCHandle::Alloc(handler);
			IntPtr slbPtr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::SetLightBrightnessFp slbFpUm = static_cast<::SimulatorControl::SetLightBrightnessFp>(slbPtr.ToPointer());
			simCon->SetDelegatorSetLightBrightnessFp(slbFpUm);
		}
		virtual void SetDelegatorSetLightStatus(RobotBase::SetLightStatusHandler^ handler)
		{
			slsGC = GCHandle::Alloc(handler);
			IntPtr slsPtr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::SetLightStatusFp slsFpUm = static_cast<::SimulatorControl::SetLightStatusFp>(slsPtr.ToPointer());
			simCon->SetDelegatorSetLightStatusFp(slsFpUm);
		}
		virtual void SetDelegatorSendMessage(RobotBase::SendMessageHandler^ handler)
		{
			smGC = GCHandle::Alloc(handler);
			IntPtr smPtr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::SendMessageFp smFpUm = static_cast<::SimulatorControl::SendMessageFp>(smPtr.ToPointer());
			simCon->SetDelegatorSendMessageFp(smFpUm);
		}
		virtual void SetDelegatorReceiveMessage(RobotBase::ReceiveMessageHandler^ handler)
		{
			rmGC = GCHandle::Alloc(handler);
			IntPtr ptr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::ReceiveMessageFp fp = static_cast<::SimulatorControl::ReceiveMessageFp>(ptr.ToPointer());
			simCon->SetDelegatorReceiveMessageFp(fp);

		}
		virtual void SetDelegatorClearMessage(RobotBase::ClearMessageHandler^ handler)
		{
			cmGC = GCHandle::Alloc(handler);
			IntPtr cmPtr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::ClearMessageFp cmFpUm = static_cast<::SimulatorControl::ClearMessageFp>(cmPtr.ToPointer());
			simCon->SetDelegatorClearMessageFp(cmFpUm);
		}
		virtual void SetDelegatorOrderMotor(RobotBase::OrderMotorHandler^ handler)
		{
			omGC = GCHandle::Alloc(handler);
			IntPtr omPtr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::OrderMotorFp omFpUm = static_cast<::SimulatorControl::OrderMotorFp>(omPtr.ToPointer());
			simCon->SetDelegatorOrderMotorFp(omFpUm);
		}
		virtual void SetDelegatorCputCLCD(RobotBase::CputCLCDHandler^ handler)
		{
			cclGC = GCHandle::Alloc(handler);
			IntPtr cclPtr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::CputCLCDFp cclFpUm = static_cast<::SimulatorControl::CputCLCDFp>(cclPtr.ToPointer());
			simCon->SetDelegatorCputCLCDFp(cclFpUm);
		}
		virtual void SetDelegatorCputWLCD(RobotBase::CputWLCDHandler^ handler)
		{
			ccwGC = GCHandle::Alloc(handler);
			IntPtr ccwPtr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::CputWLCDFp ccwFpUm = static_cast<::SimulatorControl::CputWLCDFp>(ccwPtr.ToPointer());
			simCon->SetDelegatorCputWLCDFp(ccwFpUm);
		}
		virtual void SetDelegatorCputSLCD(RobotBase::CputSLCDHandler^ handler)
		{
			ccsGC = GCHandle::Alloc(handler);
			IntPtr ccsPtr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::CputSLCDFp ccsFpUm = static_cast<::SimulatorControl::CputSLCDFp>(ccsPtr.ToPointer());
			simCon->SetDelegatorCputSLCDFp(ccsFpUm);
		}
		virtual void SetDelegatorClearLCD(RobotBase::ClearLCDHandler^ handler)
		{
			clGC = GCHandle::Alloc(handler);
			IntPtr clPtr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::ClearLCDFp clFpUm = static_cast<::SimulatorControl::ClearLCDFp>(clPtr.ToPointer());
			simCon->SetDelegatorClearLCDFp(clFpUm);
		}
		virtual void SetDelegatorPlay(RobotBase::PlayHandler^ handler)
		{
			pGC = GCHandle::Alloc(handler);
			IntPtr pPtr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::PlayFp pFpUm = static_cast<::SimulatorControl::PlayFp>(pPtr.ToPointer());
			simCon->SetDelegatorPlayFp(pFpUm);
		}
		virtual void SetDelegatorSetSoundDuration(RobotBase::SetSoundDurationHandler^ handler)
		{
			ssdGC = GCHandle::Alloc(handler);
			IntPtr ssdPtr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::SetSoundDurationFp ssdFpUm = static_cast<::SimulatorControl::SetSoundDurationFp>(ssdPtr.ToPointer());
			simCon->SetDelegatorSetSoundDurationFp(ssdFpUm);
		}
		virtual void SetDelegatorSetSoundInternote(RobotBase::SetSoundInternoteHandler^ handler)
		{
			ssiGC = GCHandle::Alloc(handler);
			IntPtr ssiPtr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::SetSoundInternoteFp ssiFpUm = static_cast<::SimulatorControl::SetSoundInternoteFp>(ssiPtr.ToPointer());
			simCon->SetDelegatorSetSoundInternoteFp(ssiFpUm);
		}
		virtual void SetDelegatorStopSound(RobotBase::StopSoundHandler^ handler)
		{
			ssGC = GCHandle::Alloc(handler);
			IntPtr ssPtr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::StopSoundFp ssFpUm = static_cast<::SimulatorControl::StopSoundFp>(ssPtr.ToPointer());
			simCon->SetDelegatorStopSoundFp(ssFpUm);
		}
		virtual void SetDelegatorBeepSound(RobotBase::BeepSoundHandler^ handler)
		{
			bsGC = GCHandle::Alloc(handler);
			IntPtr bsPtr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::BeepSoundFp bsFpUm = static_cast<::SimulatorControl::BeepSoundFp>(bsPtr.ToPointer());
			simCon->SetDelegatorBeepSoundFp(bsFpUm);
		}

		virtual void SetDelegatorNotifyLoopCount(RobotBase::NotifyLoopCountHandler^ handler)
		{
			nlcGC = GCHandle::Alloc(handler);
			IntPtr ptr = Marshal::GetFunctionPointerForDelegate(handler);
			::SimulatorControl::NotifyLoopCountFp nlcFpUm = static_cast<::SimulatorControl::NotifyLoopCountFp>(ptr.ToPointer());
			simCon->SetDelegatorNotifyLoopCount(nlcFpUm);
		}

		virtual String^ GetSensorName(Int32 port) {
			return gcnew String(simCon->getSensorName(port));
		}
		virtual String^ GetMotorName(Int32 port){
			return gcnew String(simCon->getMotorName(port));
		}
		virtual void SetSensorValue(Int32 port, Int32 value)
		{
			simCon->SetSensorValue(port,value);
		}

		virtual Int32 GetSensorValue(Int32 port)
		{
			return simCon->getSensorValue(port);
		}
		virtual void SetBatteryLevel(Int32 level)
		{
			simCon->SetBatteryLevel(level);
		}
		virtual Int32 GetBatteryLevel()
		{
			return simCon->getBatteryValue();
		}

		virtual void SendMessageToRobot(Byte msg){
			simCon->SendMessageToRobot(msg);
		}
		virtual void SetKeyStatusToRobot(Boolean onoff, Boolean run, Boolean view, Boolean prog){
			simCon->SetKeyStatusToRobot(onoff,run,view,prog);
		}

		virtual Int32 Initialize() {
			return robot->initialize(simCon);
		}
		virtual Int32 Execute(){
			return robot->execute();
		}
		virtual Int32 Terminate(){
			return robot->terminate();
		}

		void ExecuteRobot() {
			executionResult = robot->execute();
		}

		Int32 GetExecuteRobotResult()
		{
			return executionResult;
		}

		virtual String^ GetAppName(){
			return gcnew String(robot->getAppName());
		}

	protected:
		::SimulatorControl* simCon;
		::IRobot* robot;

	private:
		GCHandle ssmGC;
		GCHandle slbGC;
		GCHandle slsGC;
		GCHandle smGC;
		GCHandle rmGC;
		GCHandle cmGC;
		GCHandle omGC;
		GCHandle cclGC;
		GCHandle ccwGC;
		GCHandle ccsGC;
		GCHandle clGC;
		GCHandle pGC;
		GCHandle ssdGC;
		GCHandle ssiGC;
		GCHandle ssGC;
		GCHandle bsGC;
		GCHandle nlcGC;

		Int32 executionResult;

};
}